package com.sc.nft.service.impl;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.sc.nft.dao.BoxItemDao;
import com.sc.nft.dao.DigitalCollectionDao;
import com.sc.nft.dao.DigitalCollectionProductInfoDao;
import com.sc.nft.dao.ProductStockDao;
import com.sc.nft.entity.BoxItem;
import com.sc.nft.entity.DigitalCollectionProductInfo;
import com.sc.nft.entity.ProductStock;
import com.sc.nft.entity.ProductStockDetail;
import com.sc.nft.enums.ClassifyType;
import com.sc.nft.enums.CommodityType;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.ProductStockService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.WeChatUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 商品库存表服务接口实现
 *
 * @author zxy
 * @description 由 Mybatisplus Code Generator 创建
 * @since 2022-06-03 01:43:54
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ProductStockServiceImpl implements ProductStockService {
    private final ProductStockDao productStockDao;
    private final DigitalCollectionProductInfoDao digitalCollectionProductInfoDao;
    private final DigitalCollectionDao digitalCollectionDao;
    private final BoxItemDao boxItemDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void subStock(Long productId, Long relationId, Integer count, Long userId, CommodityType commodityType)  {
        productStockDao.subStock(productId, relationId, count);
        ProductStockDetail stockDetail = new ProductStockDetail();
        stockDetail.setProductId(productId);
        stockDetail.setRelationId(relationId);
        stockDetail.setStockChange(0 - count);
        stockDetail.setUserId(userId);
        stockDetail.setType(commodityType);
        stockDetail.insert();
    }

    @Override
    public Boolean subItemStock(Long productId, Long relationId, Long itemId, Integer count, Long userId, CommodityType commodityType)  {
        Boolean flag = productStockDao.subItemStock(productId, relationId, itemId, count);
        ProductStockDetail stockDetail = new ProductStockDetail();
        stockDetail.setProductId(productId);
        stockDetail.setRelationId(relationId);
        stockDetail.setRelationId(itemId);
        stockDetail.setStockChange(0 - count);
        stockDetail.setUserId(userId);
        stockDetail.setType(commodityType);
        stockDetail.insert();
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void subIntegralStock(Long productId, Long relationId, Long itemId, Integer count, Long userId, CommodityType commodityType) throws GlobalRunTimeException {
        ProductStock productStock = productStockDao.getProductStock(productId, relationId, itemId);
        Assert.isTrue(productStock.getUsableCount() >= count, () -> new GlobalRunTimeException(ErrorCode.COLLECTION_IS_SOLD_OUT));
        productStock.setUsableCount(productStock.getUsableCount() - count);
        productStock.setSellCount(productStock.getSellCount() + count);
        Assert.isTrue(productStock.updateById(), () -> new GlobalRunTimeException(ErrorCode.LATER_TRY));
        ProductStockDetail stockDetail = new ProductStockDetail();
        stockDetail.setProductId(productId);
        stockDetail.setRelationId(relationId);
        stockDetail.setItemId(itemId);
        stockDetail.setStockChange(0 - count);
        stockDetail.setUserId(userId);
        stockDetail.setType(commodityType);
        stockDetail.insert();
    }

    @Override
    public ProductStock getProductStock(Long productId, Long boxId, Long itemId) {
        return productStockDao.getProductStock(productId, boxId, itemId);
    }

    @Override
    public void frozenCount(Long productId, Long boxId, int count) throws GlobalException {
        ProductStock productStock = productStockDao.getProductStock(productId, boxId, null);
        Assert.isTrue(productStock.getUsableCount() >= count, () -> new GlobalException(ErrorCode.COLLECTION_IS_SOLD_OUT));
        boolean result = productStockDao.frozenStock(productId, boxId, productStock.getVersion(), count);
        Assert.isTrue(result, () -> new GlobalException(ErrorCode.LATER_TRY));
    }

    @Override
    public void SubFrozenCount(Long productId, Long boxId, int count) throws GlobalException {
        ProductStock productStock = productStockDao.getProductStock(productId, boxId, null);
        boolean result = productStockDao.subFrozenStock(productId, boxId, productStock.getVersion(), count);
        Assert.isTrue(result, () -> new GlobalException(ErrorCode.LATER_TRY));

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void collectionStockBack(DigitalCollectionProductInfo digitalCollectionProductInfo) {
        //查询所有还未归还库存的商品

        //当前时间在结束时间之后,或者商品是已结束状态,或者是已售罄状态
        if (digitalCollectionProductInfo.getProductType() == 3 || digitalCollectionProductInfo.getIsSoldOut()) {
            //是藏品直接将商品库存表中的 (总库存-售卖库存=需要归还的库存) 加到藏品的可用库存
            if (digitalCollectionProductInfo.getTypeClassify() == ClassifyType.COLLECTION) {
                //商品库存表
                ProductStock productStock = productStockDao.getProductStock(digitalCollectionProductInfo.getId(), digitalCollectionProductInfo.getRelationId(), null);
                //(总库存-售卖库存=需要归还的库存)
                int count = productStock.getUsableCount();
                //商品没有冻结库存时才归还库存
                if (productStock.getFrozenCount() == 0) {
                    digitalCollectionDao.collectionStockBack(digitalCollectionProductInfo.getRelationId(), count);
                    //修改商品的归还库存的状态
                    digitalCollectionProductInfoDao.updateIsBackStock(digitalCollectionProductInfo.getId());
                    //修改商品库存的可用库存
                    productStockDao.udateUsableCount(productStock.getId());
                } else {
                    WeChatUtil.sendWeChatMessage("归还库存操作有商品有冻结库存请查看是否需要手动处理,归还商品ID:"+ JSON.toJSONString(productStock));
                }

            } else {
                //盲盒库存
                ProductStock productStock1 = productStockDao.getProductStock(digitalCollectionProductInfo.getId(), digitalCollectionProductInfo.getRelationId(), null);
                //盲盒没有冻结库存时才归还库存
                if (productStock1.getFrozenCount() == 0) {
                    //盲盒子项库存
                    List<ProductStock> boxItemStock = productStockDao.getBoxItemBackStock(digitalCollectionProductInfo.getId(), digitalCollectionProductInfo.getRelationId());
                    for (ProductStock productStock : boxItemStock) {
                        int count = productStock.getSumCount() - productStock.getSellCount();
                        //获取盲盒子项
                        BoxItem boxItem = boxItemDao.getById(productStock.getItemId());
                        digitalCollectionDao.collectionStockBack(boxItem.getCollectionId(), count);
                        productStockDao.udateUsableCount(productStock.getId());
                    }
                    productStockDao.udateUsableCount(productStock1.getId());
                    //修改商品的归还库存的状态
                    digitalCollectionProductInfoDao.updateIsBackStock(digitalCollectionProductInfo.getId());
                } else {
                    WeChatUtil.sendWeChatMessage("归还库存操作有商品有冻结库存请查看是否需要手动处理,归还商品ID:"+ JSON.toJSONString(productStock1));
                }

            }
        }
    }

    @Override
    public Boolean deductStock(Long productId, Long relationId, Integer count, Long userId, CommodityType commodityType) {
        Boolean aBoolean = productStockDao.deductStock(productId, relationId, count);
        if(aBoolean){
            ProductStockDetail stockDetail = new ProductStockDetail();
            stockDetail.setProductId(productId);
            stockDetail.setRelationId(relationId);
            stockDetail.setStockChange(0 - count);
            stockDetail.setUserId(userId);
            stockDetail.setType(commodityType);
            stockDetail.insert();
        }
        return aBoolean;
    }
}